package cc.shacocloud.mirage.utils.converter;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * 用于转换器缓存的密钥
 *
 * @see TypeConverterSupport
 */
public final class ConverterCacheKey implements Comparable<ConverterCacheKey> {
    
    private final TypeDescriptor sourceType;
    
    private final TypeDescriptor targetType;
    
    public ConverterCacheKey(TypeDescriptor sourceType, TypeDescriptor targetType) {
        this.sourceType = sourceType;
        this.targetType = targetType;
    }
    
    /**
     * 创建 {@link ConverterCacheKey} 对象的快捷方法
     */
    @Contract(value = "_, _ -> new", pure = true)
    public static @NotNull ConverterCacheKey of(TypeDescriptor sourceType, TypeDescriptor targetType) {
        return new ConverterCacheKey(sourceType, targetType);
    }
    
    @Override
    public boolean equals(@Nullable Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof ConverterCacheKey)) {
            return false;
        }
        ConverterCacheKey otherKey = (ConverterCacheKey) other;
        return (this.sourceType.equals(otherKey.sourceType)) &&
                this.targetType.equals(otherKey.targetType);
    }
    
    @Override
    public int hashCode() {
        return (this.sourceType.hashCode() * 29 + this.targetType.hashCode());
    }
    
    @Contract(pure = true)
    @Override
    public @NotNull String toString() {
        return ("ConverterCacheKey [sourceType = " + this.sourceType +
                ", targetType = " + this.targetType + "]");
    }
    
    @Override
    public int compareTo(@NotNull ConverterCacheKey other) {
        int result = this.sourceType.getResolvableType().toString().compareTo(
                other.sourceType.getResolvableType().toString());
        if (result == 0) {
            result = this.targetType.getResolvableType().toString().compareTo(
                    other.targetType.getResolvableType().toString());
        }
        return result;
    }
}